package com.yekaile.carsystem.service;

import cn.hutool.core.date.DateUtil;
import com.yekaile.carsystem.controller.vo.MenuVO;
import com.yekaile.carsystem.controller.vo.PermissionVO;
import com.yekaile.carsystem.controller.vo.UserVO;
import com.yekaile.carsystem.entity.*;
import com.yekaile.carsystem.mapper.SystemAuthorityMapper;
import com.yekaile.carsystem.mapper.UserMapper;
import com.yekaile.carsystem.mapper.UserRoleMapper;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author yekaile
 */
@Service
@AllArgsConstructor(onConstructor_ = {@Autowired})
public class UserServiceImpl implements UserService {


    UserMapper userMapper;

    SystemAuthorityMapper systemAuthorityMapper;

    UserRoleMapper userRoleMapper;



    @Override
    public User getUser(Integer userId) {
        return userMapper.selectByPrimaryKey(userId);
    }

    @Override
    public User getUser(String username) {

        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<User> list = userMapper.selectByExample(example);
        return list.size() != 0 ? list.get(0) : null;
    }

    @Override
    public List<Role> getRoles(Integer userId) {
        return userMapper.selectRoles(userId);
    }

    @Override
    public Set<String> getRoleNames(Integer userId) {
        return getRoles(userId).stream().map(Role::getRoleName).collect(Collectors.toSet());
    }


    @Override
    public Set<SystemAuthority> getAuthorities(Integer userId) {

        Set<SystemAuthority> systemAuthorities = new HashSet<>(userMapper.selectAuthorities(getRoles(userId).
                stream().
                map(Role::getRoleId).
                collect(Collectors.toList())));
        Set<SystemAuthority> systemAuthorities1 = new HashSet<>(userMapper.selectOnlyUserAuthority(userId));
        systemAuthorities.addAll(systemAuthorities1);
        return systemAuthorities;

    }


    public Set<MenuVO> getAuthorityOne(Set<SystemAuthority> systemAuthorities) {
        List<SystemAuthority> list = new ArrayList<>(systemAuthorities);
        Set<MenuVO> menuSet = new HashSet<>();
        Set<String> set = new HashSet<>();
        for (int i = 0; i < list.size(); i++) {
            SystemAuthority authority = list.get(i);
            if (!set.contains(authority.getMenuCode())) {
                MenuVO menuVO = new MenuVO();
                Set<PermissionVO> permissionSet = new HashSet<>();
                set.add(authority.getMenuCode());
                menuVO.setMenuCode(authority.getMenuCode());
                menuVO.setMenuName(authority.getMenuName());

                for (int j = i; j < list.size(); j++) {
                    SystemAuthority systemAuthority = list.get(j);
                    if (set.contains(systemAuthority.getMenuCode()) && systemAuthority.getMenuCode().equals(authority.getMenuCode())) {
                        permissionSet.add(new PermissionVO(systemAuthority.getDescription(), systemAuthority.getPermission()));
                    }
                }
                menuVO.setPermissionList(permissionSet);
                menuSet.add(menuVO);
            }
        }
        return menuSet;
    }

    @Override
    public Set<MenuVO> getMenuVOS(Integer userId) {

        Set<SystemAuthority> systemAuthorities = getAuthorities(userId);
        return getAuthorityOne(systemAuthorities);
    }


    @Override
    public Set<MenuVO> getAllMenuVO() {
        Set<SystemAuthority> systemAuthoritySet = new HashSet<>(systemAuthorityMapper.selectAll());
        return getAuthorityOne(systemAuthoritySet);
    }

    @Override
    public List<User> getAllUser() {
        return userMapper.selectAll();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addUser(UserVO userVO) {
        User user = userVO.getUser();
        userMapper.insertSelective(user);
        return getInteger(userVO, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateUser(UserVO userVO) {
        User user = userVO.getUser();
        user.setGmtModified(DateUtil.now());
        userMapper.updateByPrimaryKeySelective(user);
        UserRoleExample example = new UserRoleExample();
        UserRoleExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(user.getUserId());
        userRoleMapper.deleteByExample(example);
        return getInteger(userVO, user);
    }


    private Integer getInteger(UserVO userVO, User user) {
        List<Role> roles = userVO.getRoles();
        List<UserRole> userRoles = new ArrayList<>();
        roles.forEach(role -> {
            UserRole userRole = new UserRole();
            userRole.setRoleId(role.getRoleId());
            userRole.setGmtCreated(DateUtil.now());
            userRole.setGmtModified(DateUtil.now());
            userRole.setIsDeleted(0);
            userRole.setUserId(user.getUserId());
            userRoles.add(userRole);
        });
        return userRoleMapper.batchInsert(userRoles);
    }

    @Override
    public Integer deleteUser(Integer userId) {
        User user = userMapper.selectByPrimaryKey(userId);
        user.setIsDeleted(1);
        return userMapper.updateByPrimaryKeySelective(user);
    }


    @Override
    public List<PermissionVO> getPermissionVOS(Integer userId) {
        return getAuthorities(userId).stream().map(en -> new PermissionVO(en.getDescription(), en.getPermission())).collect(Collectors.toList());
    }

    @Override
    public Set<String> getAuthorityNames(Integer userId) {
        return getAuthorities(userId).stream().map(SystemAuthority::getPermission).collect(Collectors.toSet());

    }


}
